package cn.wolfcode.luowowo.search.service.impl;

import cn.wolfcode.luowowo.search.domain.StrategyTemplate;
import cn.wolfcode.luowowo.search.query.StrategySearchQuery;
import cn.wolfcode.luowowo.search.repository.StrategySearchRepository;
import cn.wolfcode.luowowo.search.service.IStrategySearchService;
import cn.wolfcode.luowowo.search.vo.StatisVo;
import com.alibaba.dubbo.config.annotation.Service;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.aggregations.bucket.composite.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import java.util.*;

@Service
public class StrategySearchServiceImpl implements IStrategySearchService{

    @Autowired
    private StrategySearchRepository repository;

    @Autowired
    private ElasticsearchTemplate template;

    @Override
    public void saveOrUpdate(StrategyTemplate template) {

        repository.save(template);
    }

    @Override
    public List<Map<String, Object>> queryThemeTop10() {
        List<Map<String, Object>> list = new ArrayList<>();
        Map<String,Object> map =null;
        List<StatisVo> vos = statisVoGroup("themeId", "themeName", "themeGroup",null);
        for (StatisVo statisVo : vos) {
            //目的地列表 :通过主题id查询目的地集合
            List<StatisVo> dests = queryDestsByThemeId(statisVo.getId());
            map = new HashMap<>();
            map.put("theme", statisVo);
            map.put("dests", dests);
            list.add(map);
        }


        //只需要前十个
        if (list.size() >10){
            //如果超过10个的话就不要了
            list=list.subList(0,10);
        }

        return list;
    }

    //分组查询
    private List<StatisVo> statisVoGroup(String idField,String nameField,String groupName,
        BoolQueryBuilder query
    ){
        List<CompositeValuesSourceBuilder<?>> sources =new ArrayList<>();
        TermsValuesSourceBuilder idSource = new TermsValuesSourceBuilder("id");
        //多列分组: id属性对象
        idSource.field(idField);
        //多列分组: name属性对象
        TermsValuesSourceBuilder nameSource = new TermsValuesSourceBuilder("name");
        //用哪个名字来分组(多列分组)
        nameSource.field(nameField);

        sources.add(idSource);
        sources.add(nameSource);

        //多列分组查询查询对象
        //参数1:分组查询结果操作名称
        //参数2:分组查询的列队向集合
        CompositeAggregationBuilder aggregationBuilder =
                new CompositeAggregationBuilder(groupName,sources);
        //实现相关步骤
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();

        builder.addAggregation(aggregationBuilder); //分组语句
        builder.withPageable(PageRequest.of(0,1)); //排序语句

        if(query !=null){
            builder.withQuery(query);
        }



        //查询DSL之后的结果
        AggregatedPage<StrategyTemplate> search = (AggregatedPage<StrategyTemplate>) repository.search(builder.build());
        //分组结果
        InternalComposite themeGroup = search.getAggregations().get(groupName);

        //遍历得到key下面的值
        StatisVo vo = null;
        List<StatisVo> list =new ArrayList<>();
        for (CompositeAggregation.Bucket bucket : themeGroup.getBuckets()){
            //主题
            Long id =Long.parseLong(bucket.getKey().get("id").toString());
            String name = bucket.getKey().get("name").toString();
            Long count = bucket.getDocCount();
            vo = new StatisVo(id,name,count);
            list.add(vo);
        }
        //按关联目的地数量排序
        //排序结果int 类型
        //大于0:大于 小于0:小于 等于0:等于
        Collections.sort(list, new Comparator<StatisVo>() {
            @Override
            public int compare(StatisVo o1, StatisVo o2) {
                Long ret = o2.getCount() - o1.getCount();
                return ret.intValue();
            }
        });
        return list;
    }

    @Override
    public List<StatisVo> queryConditionThemeGroup() {
        return statisVoGroup("themeId","themeName","themeGroup",null);
    }

    @Override
    public List<StatisVo> queryConditionAbroadsGroup() {

        BoolQueryBuilder query = QueryBuilders.boolQuery().mustNot(QueryBuilders.termQuery("countryId", 1));

        return statisVoGroup("countryId","countryName","countryGroup",query);
    }

    @Override
    public List<StatisVo> queryConditionProvincesGroup() {
        return statisVoGroup("provinceId","provinceName","provinceGroup",null);
    }

    @Override
    public Page query(StrategySearchQuery qo) {
        PageRequest pageable = PageRequest.of(qo.getCurrentPage() - 1, qo.getPageSize()
                , Sort.Direction.DESC, qo.getOrderBy()
        );
        TermQueryBuilder builder = null;
        //主题
        if (qo.getType()==StrategySearchQuery.CONDITION_TYPE_THEME){
            builder = QueryBuilders.termQuery("themeId",qo.getTypeValue());
        }else if(qo.getType()==StrategySearchQuery.CONDITION_TYPE_ABROAD) {
            //国家
            builder = QueryBuilders.termQuery("countryId", qo.getTypeValue());
        }else if(qo.getType()==StrategySearchQuery.CONDITION_TYPE_CHINA) {
            //身份
            builder = QueryBuilders.termQuery("provinceId", qo.getTypeValue());
        }
        if(builder !=null){
            return repository.search(builder,pageable);
        }

        return repository.findAll(pageable);
    }

    @Override
    public List<StrategyTemplate> getByDestName(String destName) {
        return repository.findByDestName(destName);
    }

    //通过主题id查询关联目的地
    private List<StatisVo> queryDestsByThemeId(Long themeId) {
        List<StrategyTemplate> list = repository.findByThemeId(themeId);
        List<StatisVo> vos = new ArrayList<>();

        //保存已经添加到list中目的地名
        ArrayList<Object> names = new ArrayList<>();

        for (StrategyTemplate strategyTemplate : list) {

            //去除重复的目的地
            if(!names.contains(strategyTemplate.getDestName())){
                StatisVo vo = new StatisVo();
                vo.setId(strategyTemplate.getDestId());
                vo.setName(strategyTemplate.getDestName());
                vos.add(vo);
                names.add(strategyTemplate.getDestName());
            }
        }

        return vos;
    }
}
